<?php
/**
 * User: Mykola B.
 * Date: 3/3/13
 * Time: 12:47 PM
 */
namespace geo {
    class Point
    {

        const earthRadius = 6371;
        const maxLatitude = 90;
        const maxLongitude = 180;
        const conversionRatio = 360000;

        public $latitude;
        public $longitude;

        private $tiedObject;

        public function __construct($latitude, $longitude, $tiedObject=null) {
            if (abs($latitude) > self::maxLatitude) $latitude /= self::conversionRatio;
            if (abs($longitude) > self::maxLongitude) $longitude /= self::conversionRatio;
            $this->latitude = $latitude;
            $this->longitude = $longitude;
            $this->tiedObject = $tiedObject;
        }

        /**
         * Calculates distance between geographical points.
         * $c is the angular distance in radians, and $a is the square of half
         * the chord length between the points.
         * @link http://en.wikipedia.org/wiki/Haversine_formula
         * @param Point $other
         */
        public function distance(Point $other) {
            $deltaLatitude = deg2rad($other->latitude - $this->latitude);
            $deltaLongitude = deg2rad($other->longitude - $this->longitude);

            $rLatitudeThis = deg2rad($this->latitude);
            $rLatitudeOther = deg2rad($this->latitude);

            $a = pow(sin($deltaLatitude / 2), 2) +
                 pow(sin($deltaLongitude / 2), 2) * cos($rLatitudeThis) * cos($rLatitudeOther);
            $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
            $distance = self::earthRadius * $c;
            return $distance;
        }

        /**
         * Distance measured in meters.
         * @param Point $other
         * @return int
         */
        public function distanceM(Point $other) {
            return $this->distance($other) * 1000;
        }

        public function get($name) {
            if (isset($this->tiedObject->$name)) {
                return $this->tiedObject->$name;
            }
            return null;
        }

    }
}
